package cn.funnymap.lgis.web;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

/**
 * @author jiao xn
 */
@Slf4j
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException,
            KeyManagementException {
        // 1. 信任所有证书（如需加强安全控制请改为指定证书）
        SSLConnectionSocketFactory scsf = new SSLConnectionSocketFactory(
                SSLContexts.custom()
                        .loadTrustMaterial((chain, authType) -> true)
                        .build(),
                NoopHostnameVerifier.INSTANCE
        );
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", scsf)
                .build();
        // 2. 连接池配置
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connManager.setMaxTotal(500); // 设置最大连接数
        connManager.setDefaultMaxPerRoute(100); // 每个地址的并发数
        
        // 3. 请求超时配置
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(10000)       // 建立连接最多10秒
                .setConnectionRequestTimeout(5000) // 从连接池获取连接的超时
                .setSocketTimeout(120000)        // 读取数据最长120秒
                .build();
        // 4. 创建 HttpClient，并使用连接池
        CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connManager) // 加上连接池
                .setDefaultRequestConfig(requestConfig)
                .evictIdleConnections(30, TimeUnit.SECONDS) // 清理闲置连接
                .setConnectionTimeToLive(60, TimeUnit.SECONDS) // 设置连接最大存活时间
                .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                .evictExpiredConnections() // 清理过期连接
                .build();
        
        
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        
        // 可选：设置 RestTemplate 的超时（与 RequestConfig 一致更保险）
        factory.setConnectTimeout(10000);
        factory.setReadTimeout(120000);
        
        return new RestTemplate(factory);
    }
}
